#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

void RunMessageLoop()
{
	MSG msg;

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return;
}

void CreateWnd(const TCHAR* szClassName, const TCHAR* szAppName)
{
	WNDCLASS wcs;
	if (FALSE != GetClassInfo(GetModuleHandle(NULL), szClassName, &wcs))
	{
		HWND hWnd = CreateWindow(szClassName, szAppName, WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 800, 480, NULL, NULL, NULL, 0);
		if (NULL != hWnd && IsWindow(hWnd))
		{
			ShowWindow(hWnd, SW_SHOW);
			UpdateWindow(hWnd);
		}
	}

	return;
}

HHOOK hHook;

LRESULT CALLBACK HookWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode >= 0)
	{
		TCHAR szTmp[MAX_PATH];
		CWPSTRUCT wps = *(CWPSTRUCT*)lParam;
		_stprintf(szTmp, _T("%d  %d  [message: %d  wParam: %d  lParam: %d]\n"), nCode, wParam, wps.message, wps.wParam, wps.lParam);
		OutputDebugString(szTmp);
	}
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	switch (nMsg)
	{
		case WM_CREATE:
		{
			struct SCtrlInfo {
				const TCHAR*	szTitle;
				UINT			nID;
			};

			SCtrlInfo CtrlInfoList[] = {
				{_T("WndMsg Hook"), 1000}, {_T("Exit App"), 1010},
			};

			int x	= 0;
			int y	= 0;
			int cx	= 100;
			int cy	= 40;
			for (int ii = 0; ii < sizeof(CtrlInfoList)/sizeof(*CtrlInfoList); ii++)
			{
				CreateWindow(_T("Button"), CtrlInfoList[ii].szTitle, WS_VISIBLE|WS_CHILD, x, y, cx, cy, hWnd, (HMENU)CtrlInfoList[ii].nID, NULL, 0);
				x += cx + 10;
			}
			
			break;
		}
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case 1000:
					hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookWndProc, GetModuleHandle(NULL), GetCurrentThreadId());
					break;
				case 1010:
					UnhookWindowsHookEx(hHook);
					DestroyWindow(hWnd);
					break;
				default:
					break;
			}
			break;
		}
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
	}

	return DefWindowProc(hWnd, nMsg, wParam, lParam);
}


bool RegisterWndClass(const TCHAR* szClassName)
{
	WNDCLASS wcs		= {0};
	wcs.cbClsExtra		= 0;
	wcs.style			= CS_HREDRAW|CS_VREDRAW;
	wcs.hbrBackground	= (HBRUSH)WHITE_BRUSH;
	wcs.lpszClassName	= szClassName;
	wcs.hCursor			= (HCURSOR)LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wcs.hInstance		= GetModuleHandle(NULL);
	wcs.lpfnWndProc		= WndProc;
	wcs.hIcon			= (HICON)LoadIcon(NULL, IDI_APPLICATION);

	return (0 != RegisterClass(&wcs));
}


BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	const TCHAR* szClassName	= _T("Win32App");
	const TCHAR* szAppName		= _T("Demo0054");
	
	if (RegisterWndClass(szClassName))
	{
		CreateWnd(szClassName, szAppName);
		RunMessageLoop();
	}

	return 0;
}